﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using HadronData;

namespace Hadron.Entities
{
    class Turret
        : LandEntity
    {
        private static Polygon s_polygonGeometry;

        private bool m_bMissile;
        private  Polygon m_polygonGeometry;
        float m_fTargetOrientation, m_fGunOrientation;
        float m_fFireReload;
        bool m_bInRange;

        public Turret(EntityMarker p_entityMarker, Environment p_environment, bool p_bMissile)
            : base(p_entityMarker, p_environment)
        {
            // construct geometry
            if (s_polygonGeometry == null)
            {
                s_polygonGeometry = new Polygon();
                s_polygonGeometry.Edges.Add(new Edge(16.0f, 0.0f, 12.0f, -8.0f));
                s_polygonGeometry.Edges.Add(new Edge(12.0f, -8.0f, -12.0f, -8.0f));
                s_polygonGeometry.Edges.Add(new Edge(-12.0f, -8.0f, -16.0f, 0.0f));

                float fAngleDelta = MathHelper.Pi / 8;
                for (int nIndex = 0; nIndex < 8; nIndex++)
                {
                    Vector2 vecVertex1 = new Vector2(
                        0.0f + (float)Math.Cos(fAngleDelta * nIndex) * 8.0f,
                        -8.0f - (float)Math.Sin(fAngleDelta * nIndex) * 8.0f);
                    Vector2 vecVertex2 = new Vector2(
                        0.0f + (float)Math.Cos(fAngleDelta * nIndex + fAngleDelta) * 8.0f,
                        -8.0f - (float)Math.Sin(fAngleDelta * nIndex + fAngleDelta) * 8.0f);
                    s_polygonGeometry.Edges.Add(new Edge(vecVertex1, vecVertex2));
                }
                s_polygonGeometry.UpdateBounds();

                // allocate 3 extra edges for gun
                s_polygonGeometry.Edges.Add(new Edge());
                s_polygonGeometry.Edges.Add(new Edge());
                s_polygonGeometry.Edges.Add(new Edge());
            }

            m_bMissile = p_bMissile;

            m_nHealth = m_bMissile ? 8 : 5;
            m_nPoints = m_bMissile ? 800 : 500;
            m_fTargetOrientation = m_fGunOrientation = -MathHelper.PiOver2;
            m_fFireReload = 0.0f;

            m_polygonGeometry = new Polygon(s_polygonGeometry);
            m_polygonGeometry.Transform(m_trnPlacement);
            m_polygonGeometry.Colour = m_bMissile ? Color.OrangeRed : new Color(0.0f, 0.25f, 1.0f);

            m_circleBounds = s_polygonGeometry.GetBoundingCircle(Vector2.Zero);
        }

        public override void Update(GameTime p_gameTime)
        {
            base.Update(p_gameTime);

            m_circleBounds.Centre = m_trnPlacement.Translation;

            float fDeltaTime = (float)p_gameTime.ElapsedGameTime.TotalSeconds;

            m_polygonGeometry.Transform(m_trnPlacement, s_polygonGeometry);

            PlayerShip playerShip = m_environment.PlayerShip;
            Vector2 vecOffset = m_trnPlacement.Inverse.Apply(playerShip.Position);
            m_fTargetOrientation = (float)Math.Atan2(vecOffset.Y, vecOffset.X);

            m_fGunOrientation += (m_fTargetOrientation - m_fGunOrientation) * fDeltaTime;

            m_bInRange = vecOffset.Length() < 256.0f;
            if (m_fGunOrientation > -MathHelper.Pi * 0.2f)
            {
                m_fGunOrientation = -MathHelper.Pi * 0.2f;
                m_bInRange = false;
            }
            if (m_fGunOrientation < -MathHelper.Pi * 0.8f)
            {
                m_fGunOrientation = -MathHelper.Pi * 0.8f;
                m_bInRange = false;
            }

            // update gun geometry
            List<Edge> listEdges = m_polygonGeometry.Edges;
            Edge edgeGun1 = listEdges[listEdges.Count - 3];
            Edge edgeGun2 = listEdges[listEdges.Count - 2];
            Edge edgeGun3 = listEdges[listEdges.Count - 1];

            Transformation trnGun = new Transformation(
                m_fGunOrientation, new Vector2(0.0f, -8.0f));
            Transformation trnCombined = m_trnPlacement.ComposeWith(trnGun);

            edgeGun1.Start = new Vector2(9.0f, 3.0f);
            edgeGun1.End = new Vector2(20.0f, 2.0f);
            edgeGun1.Transform(trnCombined);

            edgeGun2.Start = new Vector2(9.0f, -3.0f);
            edgeGun2.End = new Vector2(20.0f, -2.0f);
            edgeGun2.Transform(trnCombined);

            edgeGun3.Start = new Vector2(20.0f, -2.0f);
            edgeGun3.End = new Vector2(20.0f, 2.0f);
            edgeGun3.Transform(trnCombined);

            if (m_fFireReload > 0.0f)
                m_fFireReload -= fDeltaTime;

            if (m_bInRange && m_fFireReload <= 0.0f)
            {
                Vector2 vecProjectilePosition = trnCombined.Apply(new Vector2(16.0f, 0.0f));
                EnemyPlasma enemyPlasma = new EnemyPlasma(
                    m_environment, m_bMissile, vecProjectilePosition);

                enemyPlasma.Position = vecProjectilePosition;
                Vector2 vecVelocity = trnCombined.RotationDirection * 64.0f;
                enemyPlasma.Velocity = vecVelocity;
                m_environment.EnemyProjectiles.Add(enemyPlasma);
                m_fFireReload += 2.0f;
            }
        }

        public override void Draw(SpriteBatch p_spriteBatch)
        {
            m_polygonGeometry.Draw(p_spriteBatch);
        }

        public override EntityType Type
        {
            get { return EntityType.GunTurret; }
        }

        public override bool Destructuble
        {
            get { return true; }
        }

        public override bool Hostile
        {
            get { return true; }
        }

        public override Geometry Geometry
        {
            get { return m_polygonGeometry; }
        }
    }
}
